package com.lining.orangeservice.filter;

import com.lining.orangeservice.entity.po.Permission;
import com.lining.orangeservice.service.PermissionService;
import com.lining.orangeservice.utils.JwtUtil;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.List;

/**
 * 权限授权过滤器
 *
 * 该过滤器用于基于URL路径进行权限检查
 * 在JWT认证之后但在业务逻辑之前执行
 */
@Component
@RequiredArgsConstructor
public class PermissionAuthorizationFilter extends OncePerRequestFilter {

    private final JwtUtil jwtUtil;
    
    @Autowired
    private PermissionService permissionService;

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        // 白名单路径不需要权限检查
        String[] whiteList = {"/auth/login", "/login", "/auth/register", "/captcha/get"};
        String requestURI = request.getRequestURI();
        
        for (String pattern : whiteList) {
            if (requestURI.equals(pattern)) {
                return true;
            }
        }
        
        // Swagger相关路径也不需要权限检查
        if (requestURI.startsWith("/doc.html") || 
            requestURI.startsWith("/webjars/") || 
            requestURI.startsWith("/v3/api-docs/") || 
            requestURI.startsWith("/swagger-resources/") || 
            requestURI.startsWith("/swagger-ui/")) {
            return true;
        }
        
        return false;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, 
                                  HttpServletResponse response, 
                                  FilterChain filterChain) throws ServletException, IOException {
        
        try {
            // 获取当前认证信息
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            
            // 如果没有认证信息，则直接放行（由后续的Spring Security处理）
            if (authentication == null || !authentication.isAuthenticated()) {
                filterChain.doFilter(request, response);
                return;
            }
            
            // 获取请求的URL
            String requestURI = request.getRequestURI();
            
            // 从Token中获取用户ID
            String token = getTokenFromRequest(request);
            if (StringUtils.hasText(token) && jwtUtil.validateToken(token)) {
                Long userId = jwtUtil.getUserIdFromToken(token);
                
                // 根据用户ID获取用户权限列表（而非所有权限）
                List<Permission> userPermissions = permissionService.getPermissionsByUserId(userId);
                
                // 检查用户是否有访问该URL的权限
                boolean hasPermission = checkPermission(requestURI, userPermissions);
                
                if (!hasPermission) {
                    // 如果没有权限，抛出访问拒绝异常
                    throw new AccessDeniedException("没有访问该资源的权限");
                }
            } else {
                // Token无效或不存在，抛出认证异常
                throw new AccessDeniedException("认证失败，请重新登录");
            }
            
        } catch (AccessDeniedException e) {
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"code\": 403, \"message\": \"" + e.getMessage() + "\"}");
            return;
        } catch (Exception e) {
            logger.error("权限检查失败：{}",  e);
        }
        
        // 继续执行过滤器链
        filterChain.doFilter(request, response);
    }
    
    /**
     * 检查用户是否有访问指定URL的权限
     * 
     * @param requestURI 请求的URL
     * @param userPermissions 用户拥有的权限列表
     * @return 是否有权限
     */
    private boolean checkPermission(String requestURI, List<Permission> userPermissions) {
        // 精确匹配权限路径
        for (Permission permission : userPermissions) {
            if (permission.getPath() != null && requestURI.equals(permission.getPath())) {
                return true;
            }
        }
        
        // 如果没有找到匹配的权限，默认拒绝访问（更安全的做法）
        return false;
    }
    
    /**
     * 从HTTP请求头中提取JWT Token
     * 
     * @param request HTTP请求对象
     * @return 提取到的JWT Token，如果没有则返回null
     */
    private String getTokenFromRequest(HttpServletRequest request) {
        // 从请求头中获取Authorization字段
        String bearerToken = request.getHeader("Authorization");
        
        // 检查Authorization字段是否存在且以"Bearer "开头
        // JWT Token通常以"Bearer "作为前缀
        if (bearerToken != null && bearerToken.startsWith("Bearer "))
            // 返回Bearer后面的Token部分（去掉前7个字符"Bearer "）
            return bearerToken.substring(7);
        return null;
    }
}